#! /usr/bin/env python

import urlparse
import httplib
import json
import urllib

class TaskQueueError(Exception):
    """Base class for all exceptions raised by this module.
    """
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return str(self.value)

class TaskQueue:
    def __init__(self, request_api, response_api, lock):
        self.req_api = self._parseurl(request_api)
        self.res_api = self._parseurl(response_api)

        self.lock = lock

        # id: (task, result)
        self._queue      = {}
        self._ready      = []
        self._running    = []
        self._complete   = []

    def _parseurl(self, url):
        return urlparse.urlparse(url)

    def _load(self, number = 15):
        print 'loading'
        host = self.req_api.hostname
        port = self.req_api.port
        path = self.req_api.path
        if self.req_api.port:
            con = httplib.HTTPConnection(host, port)
        else:
            con = httplib.HTTPConnection(host)
        con.request('GET', path)
        response = con.getresponse()
        if response.status != 200:
            raise TaskQueueError('Task centre has fault')

        for tobj in json.loads(response.read()):
            id      = tobj['id']
            task    = tobj['task']
            self._queue[id] = (task, None)
            self._ready.append(id)
        con.close()

    def _lock(self):
        self.lock.lock()

    def _unlock(self):
        self.lock.unlock()

    def get(self):
        try:
            _id = self._ready.pop(0)
            self._running.append(_id)
            task = self._queue[_id][0]
        except IndexError:
            self._load()
            try:
                _id = self._ready.pop(0)
                self._running.append(_id)
                task = self._queue[_id][0]
            except IndexError:
                raise TaskQueueError('Both queue and centre are emtpy')

        return _id, task

    def complete(self, results):
        self._lock()
        for _id, result in results:
            self._running.remove(_id)
            self._complete.append(_id)
            self._queue[_id][1] = result
        self._unlock()

    def respond(self):
        self._lock()
        results = [{"id": i, "result": self._queue[i][1]} for i in self._complete]
        self._unlock()

if __name__ == '__main__':
    import time
    from lock import Lock
    lock = Lock('.', 'taskqueue_test')

    taskqueue = TaskQueue('http://host/task.php', '', lock)

    while True:
        taskqueue.get()
